// https://www.lintcode.com/problem/valid-number/description


// 输入
// "e"
// 期望答案
// false

// 输入
// "1 "
// 期望答案
// true

// 输入
// " "
// 期望答案
// false

// 输入
// ".1"
// 期望答案
// true

// 输入
// "."
// 期望答案
// false

// 输入
// " 0"
// 期望答案
// true

// 输入
// "1."
// 期望答案
// true

// 输入
// " ."
// 期望答案
// false

// 输入
// "+.8"
// 期望答案
// true


// 法一：考虑corner case

class Solution {
public:
    /**
     * @param s: the string that represents a number
     * @return: whether the string is a valid number
     */

	// (+/-)3.56(e(+/-)6) 空格
	// 符号 + 浮点数 + e + 符号 + 整数
    
    // 去除空格，转换为三种：整数/浮点数/科学计数法。
    // 此题浮点数规则：至多一个小数点，至少一个数字
    
    bool isNumber(string &s) {
       s = s + " ";
        // 防止越界可以给数组多开一位
        // 这样就不用每次判断
       int i = 0;
       int l = s.size();
       while (s[i] == ' ')
       {
           i++;
       }
       if (s[i] == '+' || s[i] == '-')
       {
           i++;
       }
       int nDigit = 0;
       int nDot = 0;
       while ((s[i] >= '0' && s[i] <= '9') || s[i] == '.')
       {
           if (s[i] >= '0' && s[i] <= '9')
           {
               nDigit++;
           }
           else
           {
               nDot++;
           }
           i++;
       }
       if (nDigit <= 0 || nDot > 1)
       {
           return false;
       }
       
       if (s[i] == 'e')
       {
           i++;
           if (s[i] == '+' || s[i] == '-')
           {
                i++;     
           }
           if (i == l)
           {
               return false;
           }
           while (s[i] >= '0' && s[i] <= '9')
           {
               i++;
           }
       }
       while (s[i] == ' ')
       {
           i++;
       }
       
       return i == l;       
    }
};



// 法二：有限状态自动机(DFA)？
// class Solution {
// public:
    // bool isNumber(const string &s) {
        // enum InputType {
            // INVALID,    // 0
            // SPACE,      // 1
            // SIGN,       // 2
            // DIGIT,      // 3
            // DOT,        // 4
            // EXPONENT,   // 5
            // NUM_INPUTS  // 6
        // };
        // const int transitionTable[][NUM_INPUTS] = {
                // -1, 0, 3, 1, 2, -1, // next states for state 0
                // -1, 8, -1, 1, 4, 5,     // next states for state 1
                // -1, -1, -1, 4, -1, -1,     // next states for state 2
                // -1, -1, -1, 1, 2, -1,     // next states for state 3
                // -1, 8, -1, 4, -1, 5,     // next states for state 4
                // -1, -1, 6, 7, -1, -1,     // next states for state 5
                // -1, -1, -1, 7, -1, -1,     // next states for state 6
                // -1, 8, -1, 7, -1, -1,     // next states for state 7
                // -1, 8, -1, -1, -1, -1,     // next states for state 8
        // };

        // int state = 0;
        // for (const char c : s) {
            // InputType inputType = INVALID;
            // if (isspace(c))
                // inputType = SPACE;
            // else if (c == '+' || c == '-')
                // inputType = SIGN;
            // else if (isdigit(c))
                // inputType = DIGIT;
            // else if (c == '.')
                // inputType = DOT;
            // else if (c == 'e' || c == 'E')
                // inputType = EXPONENT;

            // // Get next state from current state and input symbol
            // state = transitionTable[state][inputType];

            // // Invalid input
            // if (state == -1) return false;
        // }
        // // If the current state belongs to one of the accepting (final) states,
        // // then the number is valid
        // return state == 1 || state == 4 || state == 7 || state == 8;

    // }
// };